﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace RotovapPlatform.Domain.Models.Temperature
{
	/// <summary>
	/// 智能温度判别数据类，用于存储和分析旋蒸过程中的温度变化数据
	/// </summary>
	public class TemperatureJudgmentData
	{
		// 历史温度数据存储
		private List<(DateTime Time, double Temperature)> _temperatureHistory = new List<(DateTime, double)>();

		// 温度稳定性分析参数
		public double StableThreshold { get; set; } = 0.3; // 温度稳定阈值，连续一段时间波动小于此值认为温度稳定
		public int StableCountRequired { get; set; } = 6;  // 需要连续稳定的检查次数
		public int StableCount { get; private set; } = 0;  // 当前连续稳定的次数

		// 峰值检测和稳定最低点参数
		public double HighestTemperature { get; private set; } = 0;  // 记录监测过程中的最高温度
		public double LowestTemperatureAfterPeak { get; private set; } = double.MaxValue; // 峰值后的最低温度
		public bool FoundPeak { get; private set; } = false;  // 是否已发现温度峰值并开始下降
		public bool TemperatureStabilized { get; private set; } = false;  // 当前温度是否稳定
		public double CurrentStableTemperature { get; private set; } = 0;  // 当前稳定状态的温度

		// 温度趋势分析
		private int _continuousDecreaseCount = 0;  // 连续下降的检测次数
		private double _previousTemperature = 0;   // 前一次检测的温度

		// 温度预测相关参数
		private double _predictionAlpha = 0.3; // 指数平滑预测的平滑系数
		private List<double> _smoothedValues = new List<double>(); // 指数平滑后的值列表
		private List<double> _trendValues = new List<double>(); // 趋势值列表

		// 温度在峰值后再次稳定的判断
		private int _stableAfterPeakCount = 0;     // 温度在峰值后稳定的次数计数
		public int StableAfterPeakRequired { get; set; } = 10;  // 需要保持稳定的检查次数
		private bool _hasFoundStableLowestPoint = false;  // 是否已找到峰值后的稳定最低点

		// 判别结果
		public bool IsJudgmentCompleted { get; set; } = false;  // 判别过程是否已完成
		public string JudgmentResult { get; set; } = string.Empty;  // 判别结果描述

		// 当前温度值
		public double CurrentOutletTemperature { get; private set; } = 0;  // 当前出口温度
		public double CurrentOilBathTemperature { get; set; } = 0;  // 当前油浴温度（辅助信息）

		// 时间信息
		public DateTime StartTime { get; private set; } = DateTime.MinValue;  // 开始监测时间
		public DateTime LastUpdateTime { get; private set; } = DateTime.MinValue;  // 上次更新时间

		/// <summary>
		/// 重置所有数据，准备开始新的温度判别
		/// </summary>
		public void Reset()
		{
			_temperatureHistory.Clear();
			StableCount = 0;
			HighestTemperature = 0;
			LowestTemperatureAfterPeak = double.MaxValue;
			FoundPeak = false;
			TemperatureStabilized = false;
			CurrentStableTemperature = 0;
			_continuousDecreaseCount = 0;
			_previousTemperature = 0;
			_stableAfterPeakCount = 0;
			_hasFoundStableLowestPoint = false;
			IsJudgmentCompleted = false;
			JudgmentResult = string.Empty;
			CurrentOutletTemperature = 0;
			StartTime = DateTime.Now;
			LastUpdateTime = DateTime.MinValue;
			_smoothedValues.Clear();
			_trendValues.Clear();
		}

		/// <summary>
		/// 添加一个温度读数
		/// </summary>
		/// <param name="temperature">当前温度</param>
		public void AddTemperature(double temperature)
		{
			// 记录当前温度
			CurrentOutletTemperature = temperature;
			LastUpdateTime = DateTime.Now;

			// 记录出口温度历史
			_temperatureHistory.Add((LastUpdateTime, temperature));

			// 保留最近一段时间的温度数据（约10分钟）
			if (_temperatureHistory.Count > 60)
			{
				_temperatureHistory.RemoveAt(0);
			}

			// 更新指数平滑预测数据
			UpdateExponentialSmoothingData(temperature);

			// 更新最高温度记录
			if (temperature > HighestTemperature)
			{
				HighestTemperature = temperature;
			}

			// 如果已发现峰值，跟踪最低温度
			if (FoundPeak)
			{
				if (temperature < LowestTemperatureAfterPeak)
				{
					LowestTemperatureAfterPeak = temperature;
					// 发现新的最低点，重置稳定计数
					_stableAfterPeakCount = 0;
					_hasFoundStableLowestPoint = false;
				}
			}

			// 检测连续下降趋势
			if (_previousTemperature > 0)
			{
				if (temperature < _previousTemperature)
				{
					_continuousDecreaseCount++;
				}
				else
				{
					_continuousDecreaseCount = 0;
				}
			}
			_previousTemperature = temperature;
		}

		/// <summary>
		/// 更新指数平滑预测数据
		/// </summary>
		/// <param name="newValue">新的温度值</param>
		private void UpdateExponentialSmoothingData(double newValue)
		{
			// 第一个值直接作为平滑值
			if (_smoothedValues.Count == 0)
			{
				_smoothedValues.Add(newValue);
				_trendValues.Add(0); // 初始趋势为0
				return;
			}

			double lastSmoothed = _smoothedValues.Last();
			double lastTrend = _trendValues.Last();

			// 计算新的平滑值
			double newSmoothed = _predictionAlpha * newValue + (1 - _predictionAlpha) * (lastSmoothed + lastTrend);

			// 计算新的趋势值
			double newTrend = _predictionAlpha * (newSmoothed - lastSmoothed) + (1 - _predictionAlpha) * lastTrend;

			_smoothedValues.Add(newSmoothed);
			_trendValues.Add(newTrend);

			// 保持列表长度与温度历史一致
			if (_smoothedValues.Count > _temperatureHistory.Count)
			{
				_smoothedValues.RemoveAt(0);
				_trendValues.RemoveAt(0);
			}
		}

		/// <summary>
		/// 预测未来温度值
		/// </summary>
		/// <param name="periodsAhead">预测未来的周期数</param>
		/// <returns>预测的温度值列表</returns>
		public List<double> PredictFutureTemperatures(int periodsAhead)
		{
			if (_smoothedValues.Count == 0 || periodsAhead <= 0)
			{
				return new List<double>();
			}

			List<double> predictions = new List<double>();
			double lastSmoothed = _smoothedValues.Last();
			double lastTrend = _trendValues.Last();

			for (int i = 1; i <= periodsAhead; i++)
			{
				double prediction = lastSmoothed + i * lastTrend;
				predictions.Add(prediction);
			}

			return predictions;
		}

		/// <summary>
		/// 获取预测的旋蒸结束时间
		/// </summary>
		/// <param name="targetTemperature">目标温度(℃)</param>
		/// <returns>预计结束时间，若无法预测则返回null</returns>
		public DateTime? PredictEndTime(double targetTemperature)
		{
			// 必须有足够的数据进行预测
			if (_temperatureHistory.Count < 10 || !FoundPeak)
			{
				return null;
			}

			// 如果当前温度已经达到或低于目标温度，返回当前时间
			if (CurrentOutletTemperature <= targetTemperature)
			{
				return DateTime.Now;
			}

			// 计算当前下降速率(℃/分钟)
			var recentPoints = _temperatureHistory.TakeLast(10).ToList();
			if (recentPoints.Count < 2) return null;

			var startPoint = recentPoints.First();
			var endPoint = recentPoints.Last();

			double tempDifference = startPoint.Temperature - endPoint.Temperature;
			double timeDifferenceMinutes = (endPoint.Time - startPoint.Time).TotalMinutes;

			if (timeDifferenceMinutes <= 0 || tempDifference <= 0)
			{
				return null; // 时间差非正值或温度未下降
			}

			double rateOfDecline = tempDifference / timeDifferenceMinutes; // ℃/分钟

			if (rateOfDecline <= 0)
			{
				return null; // 温度不在下降
			}

			// 计算达到目标温度需要的时间
			double remainingDrop = CurrentOutletTemperature - targetTemperature;
			double estimatedMinutes = remainingDrop / rateOfDecline;

			return DateTime.Now.AddMinutes(estimatedMinutes);
		}

		/// <summary>
		/// 分析温度变化速率
		/// </summary>
		/// <param name="sampleCount">样本数量</param>
		/// <returns>温度变化速率(℃/分钟)，正值表示上升，负值表示下降</returns>
		public double AnalyzeTemperatureChangeRate(int sampleCount = 10)
		{
			if (_temperatureHistory.Count < sampleCount)
			{
				return 0;
			}

			var samples = _temperatureHistory.TakeLast(sampleCount).ToList();
			var first = samples.First();
			var last = samples.Last();

			double tempDifference = last.Temperature - first.Temperature;
			double timeSpanMinutes = (last.Time - first.Time).TotalMinutes;

			if (timeSpanMinutes <= 0)
			{
				return 0;
			}

			return tempDifference / timeSpanMinutes;
		}

		/// <summary>
		/// 检查是否检测到温度峰值
		/// </summary>
		/// <returns>是否在此次检查中发现了新的峰值</returns>
		public bool CheckPeakDetection()
		{
			// 已经找到峰值，直接返回false
			if (FoundPeak)
			{
				return false;
			}

			// 温度开始下降的判断（从最高点下降1°C以上视为开始下降）
			if (HighestTemperature > 0 && (HighestTemperature - CurrentOutletTemperature) > 1.0)
			{
				FoundPeak = true;
				return true;
			}

			return false;
		}

		/// <summary>
		/// 检查温度稳定性
		/// </summary>
		public void CheckTemperatureStability()
		{
			// 至少需要有足够的数据点来判断稳定性
			if (_temperatureHistory.Count < StableCountRequired)
			{
				return;
			}

			// 获取最近的温度数据
			var recentTemps = _temperatureHistory.TakeLast(StableCountRequired).Select(t => t.Temperature).ToList();
			double maxTemp = recentTemps.Max();
			double minTemp = recentTemps.Min();
			double fluctuation = maxTemp - minTemp;
			double averageTemp = recentTemps.Average();

			// 判断温度是否稳定
			if (fluctuation <= StableThreshold)
			{
				StableCount++;

				// 如果已发现峰值，且当前温度接近历史最低温度，判断最低点是否稳定
				if (FoundPeak && !_hasFoundStableLowestPoint && Math.Abs(averageTemp - LowestTemperatureAfterPeak) < 0.5) // 允许0.5°C的误差
				{
					_stableAfterPeakCount++;
				}
				else
				{
					// 不是在峰值后的最低点附近，重置稳定计数
					_stableAfterPeakCount = 0;
				}

				// 更新温度稳定状态
				if (!TemperatureStabilized && StableCount >= StableCountRequired)
				{
					TemperatureStabilized = true;
					CurrentStableTemperature = averageTemp;
				}
			}
			else
			{
				// 温度不稳定，重置计数
				StableCount = 0;
				_stableAfterPeakCount = 0; // 同时重置峰值后稳定计数

				// 如果之前已经稳定，重置稳定标志
				if (TemperatureStabilized)
				{
					CurrentStableTemperature = 0;
					TemperatureStabilized = false;
				}
			}
		}

		/// <summary>
		/// 检查是否已找到峰值后的稳定最低点
		/// </summary>
		/// <returns>是否已确认稳定最低点</returns>
		public bool CheckStableLowestPoint()
		{
			// 必须已发现峰值，且尚未确认稳定最低点
			if (!FoundPeak || _hasFoundStableLowestPoint)
			{
				return _hasFoundStableLowestPoint;
			}

			// 检查稳定计数是否达到要求
			if (_stableAfterPeakCount >= StableAfterPeakRequired)
			{
				_hasFoundStableLowestPoint = true;
				return true;
			}

			return false;
		}

		/// <summary>
		/// 获取最近的温度平均值
		/// </summary>
		/// <param name="count">要计算平均值的样本数，默认为6</param>
		/// <returns>最近温度的平均值</returns>
		public double GetRecentTemperatureAverage(int count = 6)
		{
			if (_temperatureHistory.Count == 0)
			{
				return 0;
			}

			count = Math.Min(count, _temperatureHistory.Count);
			return _temperatureHistory.TakeLast(count).Average(t => t.Temperature);
		}

		/// <summary>
		/// 获取温度历史数据
		/// </summary>
		/// <returns>温度历史数据列表的副本</returns>
		public List<(DateTime Time, double Temperature)> GetTemperatureHistory()
		{
			return new List<(DateTime, double)>(_temperatureHistory);
		}

		/// <summary>
		/// 获取当前判别状态的描述
		/// </summary>
		/// <returns>状态描述字符串</returns>
		public string GetStatusDescription()
		{
			if (IsJudgmentCompleted)
			{
				return JudgmentResult;
			}

			if (!FoundPeak)
			{
				return $"正在监测温度上升过程，当前峰值: {HighestTemperature:F1}℃";
			}

			if (_hasFoundStableLowestPoint)
			{
				double avg = GetRecentTemperatureAverage();
				return $"已确认稳定最低温度: {avg:F1}℃, 相比峰值 {HighestTemperature:F1}℃ 下降了 {(HighestTemperature - avg):F1}℃";
			}

			return $"检测到峰值 {HighestTemperature:F1}℃，正在监测温度下降过程，当前值: {CurrentOutletTemperature:F1}℃";
		}
	}
}